/* eslint-disable @typescript-eslint/no-explicit-any */
import * as PIXI from 'pixi.js'
import useMainStore from '@renderer/store/modules/useMainStore'
import { nextTick } from 'vue'
export class Ef {
  peimi: boolean // 是否开启白名单检查
  whiteList: number[] // 白名单
  blackList: number[] // 黑名单
  activate: boolean // 是否激活
  e: (e: PIXI.FederatedPointerEvent) => void // 回调函数
  f: (e: PIXI.FederatedPointerEvent) => void // 完成事件的回调函数, 表示受其他影响, 该事件所作出的反应
  fScope: number // 完成事件的作用域
  constructor(
    e: (e: PIXI.FederatedPointerEvent) => void,
    f: (e: PIXI.FederatedPointerEvent) => void = () => {},
    fScope: number = FinishScope.self,
    peimi: boolean = false,
    activate: boolean = true,
  ) {
    this.whiteList = [] //白名单
    this.blackList = [] // 黑名单
    this.e = e // 回调函数
    this.f = f // 完成事件的回调函数
    this.fScope = fScope // 完成事件的作用域
    this.peimi = peimi // 开启白名单检查
    this.activate = activate // 是否激活
  }
  // 事件管理
  ef = (event: any): void => {
    if (!this.activate) {
      return
    }
    const { uid } = event.target
    if (this.blackList.includes(uid)) {
      return
    }
    if (this.peimi && !this.whiteList.includes(uid)) {
      return
    }
    this.e(event)
  }
  // 完成回调, 并说明是否可以有后续操作
  finish = (event: any, uid: number = -1): Promise<void> => {
    this.f(event)
    if (uid === -1) {
      // 表示超出了舞台范围(浏览器或者canvas画布区域)
      return Promise.reject()
    }
    if (this.fScope === FinishScope.self && uid !== event.target.uid) {
      // 表示超出了自身范围
      return Promise.reject()
    }
    return Promise.resolve()
  }
  // 白名单添加
  whiteAdd = (...pixis: Array<PIXI.Container | PIXI.Sprite>): Ef => {
    pixis.forEach((p) => {
      p.interactive = true
      this.whiteList.push(p.uid)
    })
    return this
  }
  // 黑名单添加
  blackAdd = (...pixis: Array<PIXI.Container | PIXI.Sprite>): Ef => {
    pixis.forEach((p) => {
      this.blackList.push(p.uid)
    })
    return this
  }
  // 激活
  on = (): Ef => {
    this.activate = true
    return this
  }
  // 禁用
  off = (): Ef => {
    this.activate = false
    return this
  }
  // 阻止
  stop = (time: number = 0): Ef => {
    if (this.activate) {
      this.activate = false
      setTimeout(() => {
        this.activate = true
      }, time)
    }
    return this
  }
}

export default Ef

/** 回调函数与事件的映射 */
export const efManage = new Map()

/** 完成事件的作用域*/
export const FinishScope = {
  self: 0,
  page: 1,
}

/**
 * 创建事件对象
 * @param cb 事件回调函数
 * @param param 其他参数
 * @param param.type 事件类型
 * @param param.peimi 是否开启白名单检查
 * @param param.activate 是否激活
 * @param param.finish 完成事件的回调函数
 * @param param.fScope 完成事件的作用域
 * @returns Ef
 */
export const createEf = <T extends keyof PIXI.FederatedEventMap>(
  e: (e: any) => void,
  param: {
    type: T
    peimi?: boolean
    activate?: boolean
    finish?: (e: PIXI.FederatedPointerEvent) => void
    fScope?: number
  },
): Ef => {
  const ef = new Ef(e, param.finish, param.fScope, param.peimi, param.activate)
  efManage.set(e, ef)
  nextTick(async () => {
    const app = await useMainStore().getApp()
    app.stage.addEventListener(param.type, ef.ef)
  })
  return ef
}
